package io.renren.ssh;

import com.alibaba.fastjson.JSONObject;
import com.jcraft.jsch.JSchException;
import io.renren.common.utils.DateUtils;
import io.renren.modules.sys.entity.SysUserTokenEntity;
import io.renren.modules.sys.service.ShiroService;
import io.renren.modules.systemconfig.entity.SystemConfigServersEntity;
import io.renren.modules.systemconfig.service.SysConfigServerService;
import lombok.extern.java.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;

@Component
@ServerEndpoint("/ssh/{serverId}/{token}")
@Log
public class SSHWebsocketServer {
    private static ApplicationContext applicationContext;
    public static void setApplicationContext(ApplicationContext applicationContext) {
        SSHWebsocketServer.applicationContext = applicationContext;
    }

    private static Logger logger = LoggerFactory.getLogger(SSHWebsocketServer.class);


    public static HashMap<String,SshConnection> ServerId_SSHConn =new HashMap<>();

    public static HashMap<String,String>   session_ServerId = new HashMap<>();

    private Session ConcurrentSession  = null;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "serverId") String serverId, @PathParam(value = "token") String token) {
        try {

            ShiroService shiroService=applicationContext.getBean(ShiroService.class);
            SysUserTokenEntity tokenEntity =  shiroService.queryByToken(token);
            if(token == null||tokenEntity==null||tokenEntity.getUserId()==null){
                SshResponse response = new SshResponse(1,"登录失败请重新登录！","/error");
                try{sendMessage(session, JSONObject.toJSONString(response));}catch (Exception e1){
                    e1.printStackTrace();
                }
                session.close();
            }

            Long userId=tokenEntity.getUserId();



            if(!ServerId_SSHConn.containsKey(serverId+"-"+userId)){
                initSSHConnect(serverId,serverId+"-"+userId);
            }
            StringBuffer sb = null;
            try{
                sb = ServerId_SSHConn.get(serverId+"-"+userId).getSession().exec("pwd");
            }catch (JSchException e){
                initSSHConnect(serverId,serverId+"-"+userId);
                sb = ServerId_SSHConn.get(serverId+"-"+userId).getSession().exec("pwd");
            }
            ConcurrentSession = session;
            ServerId_SSHConn.get(serverId+"-"+userId).setPwd(sb.toString().replace("\n","").replace("\r\n",""));
            SshResponse sr = new SshResponse(0,"登录成功!\n服务器时间："+ DateUtils.formatDefault(new Date()),sb.toString());
            System.out.println("ssh返回:"+sb.toString());
            sendMessage(session, JSONObject.toJSONString(sr));
            session_ServerId.put(session.getId(),serverId+"-"+userId);
//            SshResponse response = SshUtils.runCommand(,);
//            if(response.getReturnCode()>0){
//
//            }else{
//                String pwd = response.getStdOutput();
//                ServerId_SSHConn.get(serverId+"-"+userId).setPwd(pwd);
//                response = new SshResponse("登录成功!\n服务器时间："+ DateUtils.formatDefault(new Date()),"",0,pwd);
//                response.setPwd(ServerId_SSHConn.get(serverId+"-"+userId).getPwd());
//                sendMessage(session, JSONObject.toJSONString(response));
//                session_ServerId.put(session.getId(),serverId+"-"+userId);
//            }

        } catch (Exception e) {
            e.printStackTrace();
            SshResponse response = new SshResponse(1,"服务器IO异常！","/error");
            try{sendMessage(session, JSONObject.toJSONString(response));}catch (Exception e1){
                e1.printStackTrace();
            }
        }
    }

    private void initSSHConnect(String serverId,String key) throws Exception{
        SysConfigServerService sysConfigServerService=applicationContext.getBean(SysConfigServerService.class);
        SystemConfigServersEntity se = sysConfigServerService.getById(serverId);
        if(se!=null){
            System.out.println("se.getLoginName()"+se.getLoginName());
            System.out.println("se.getSshPwd()"+se.getSshPwd());
            SshConnection  conn  = new SshConnection(se.getLoginName(),se.getSshPwd(),se.getIpAddr(),20000);

            SSHClient client = new SSHClient(se);

//            ClientSession session = SshUtils.SSH_login(conn);
            conn.setSession(client);
            ServerId_SSHConn.put(key,conn);
        }else{
            throw new SshTimeoutException("无法加载服务器信息!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(ConcurrentSession!=null&&ConcurrentSession.getId()!=null&&session_ServerId.containsKey(ConcurrentSession.getId())){
            SshConnection conn = ServerId_SSHConn.get(session_ServerId.get(ConcurrentSession.getId()));
            try{
                conn.getSession().close();
            }catch (Exception e){
                e.printStackTrace();
            }
            ServerId_SSHConn.remove(session_ServerId.get(ConcurrentSession.getId()));
            session_ServerId.remove(ConcurrentSession.getId());
            logger.info("关闭 ssh 连接："+ conn.getHostname());

        }

        logger.info("连接关闭！");
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("收到来自窗口 {}  的信息:{}" ,session.getId(), message);
        try{
            SshConnection conn = ServerId_SSHConn.get(session_ServerId.get(session.getId()));
            if(message.startsWith("cd ")){
                StringBuffer sb = conn.getSession().exec("cd "+conn.getPwd()+"  && " +message+"  && pwd");
                System.out.println("ssh返回:"+sb.toString());
                conn.setPwd(sb.toString().replace("\n","").replace("\r\n",""));
                SshResponse sr = new SshResponse(0,"",conn.getPwd());
                sendMessage(session, JSONObject.toJSONString(sr));
            }else if("top".equals(message)){
                conn.getSession().execAsync(message, new AsyncCmdCallBack() {
                    @Override
                    public void hanndle(String returnText) {
                        try{
                            SshResponse sr = new SshResponse(0,returnText,conn.getPwd());
                            sendMessage(session, JSONObject.toJSONString(sr));
                        }catch(Exception e){
                            e.printStackTrace();
                        }

                    }
                });
            }else{
                StringBuffer sb = conn.getSession().exec("cd "+conn.getPwd()+"  && " +message);
                System.out.println("ssh返回:"+sb.toString());
                SshResponse sr = new SshResponse(0,sb.toString(),conn.getPwd());
                System.out.println("ssh返回:"+sb.toString());
                sendMessage(session, JSONObject.toJSONString(sr));
            }


        }catch (Exception e){
            e.printStackTrace();
        }

    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误");
        error.printStackTrace();
    }
    public static void sendMessage(Session session,String message) throws IOException {
        log.info(message);
        session.getBasicRemote().sendText(message);
    }

    public static void main(String[] args) throws  Exception{
        SystemConfigServersEntity se = new SystemConfigServersEntity();
        se.setIpAddr("192.168.1.253");
        se.setLoginName("root");
        se.setSshPwd("123456");
        SSHClient client = new SSHClient(se);

        StringBuffer sb = client.exec("wc -l /service/backend/nohup.out");

        sb = client.exec("sed -n '433334,433344p' /service/backend/nohup.out");
        System.out.println(sb.toString());
        client.close();
    }
}